package netty.time;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * @Description: 针对断流问题的第二种解决方案
 * Although the first solution has resolved the problem with the TIME client, the modified handler does not look that clean.
 * Imagine a more complicated protocol which is composed of multiple fields such as a variable length field. Your
 * ChannelInboundHandler implementation will become unmaintainable very quickly.
 *
 * As you may have noticed, you can add more than one ChannelHandler to a ChannelPipeline, and therefore, you can split
 * one monolithic ChannelHandler into multiple modular ones to reduce the complexity of your application. For example,
 * you could split TimeClientHandler into two handlers:
 *
 * TimeDecoder which deals with the fragmentation issue, and the initial simple version of TimeClientHandler.
 * Fortunately, Netty provides an extensible class which helps you write the first one out of the box:
 * @Author: zhongyuan
 * @CreateDate: 2020/8/25
 * @Version: OSINT1.1
 */
/*
    1) ByteToMessageDecoder is an implementation of ChannelInboundHandler which makes it easy to deal with the fragmentation issue.
 */
public class TimeDecoder extends ByteToMessageDecoder {
    /*
    2)  ByteToMessageDecoder calls the decode() method with an internally maintained cumulative buffer whenever new data is received.
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        if (in.readableBytes() < 4) {
             /*
            3) decode() can decide to add nothing to out when there is not enough data in the cumulative buffer. ByteToMessageDecoder
            will call  decode() again when there is more data received.
             */
            return;
        }
        /**
         * 4) If decode() adds an object to out, it means the decoder decoded a message successfully. ByteToMessageDecoder will
         * discard the read part of the cumulative buffer. Please remember that you don't need to decode multiple messages.
         * ByteToMessageDecoder will keep calling the decode() method until it adds nothing to out.
         */
        out.add(in.readBytes(4));
    }
}